package com.kaifamiao.token.filter;

import com.alibaba.fastjson2.JSONObject;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSObject;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.MACVerifier;
import org.tinylog.Logger;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;

@WebFilter("/*")
public class TokenFilter implements Filter {

    private final String prefix = "Bearer";
    private String secret;

    @Override
    public void init(FilterConfig config) throws ServletException {
        ServletContext sc = config.getServletContext();
        secret = sc.getInitParameter( "secret" );
        if( secret == null || (secret = secret.trim()).isEmpty() ) {
            throw new RuntimeException("未在web.xml中设置secret参数");
        }
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        String uri = request.getRequestURI();
        if( uri.startsWith("/generate/token") ) {
            chain.doFilter(req, resp);
            return;
        }

        final String auth = request.getHeader( "authorization" );
        Logger.trace( auth );
        String token = auth.substring( prefix.length() );
        token = token.trim();

        JWSObject jwsObject;
        try {
            jwsObject = JWSObject.parse(token);
        } catch (Exception e) {
            Logger.error(e, "Token解析失败");
            return;
        }

        JWSVerifier verifier;
        try {
            verifier = new MACVerifier(secret);
        } catch (JOSEException e) {
            Logger.error(e, "校验器创建失败");
            return;
        }

        try {
            if( jwsObject.verify( verifier )){
                Logger.info( "验证通过" );
                String payload = jwsObject.getPayload().toString();
                Logger.info( payload );
                Map<String,Object> map = JSONObject.parseObject( payload, Map.class );
                Logger.info( map );
                Object value = map.get( "name" );
                req.setAttribute( "name", value );
                chain.doFilter(req, resp);
                return;
            }
        } catch (JOSEException e) {
            Logger.error(e);
            return;
        }

        Logger.trace("验证失败");
    }

    @Override
    public void destroy() {

    }

}
